#ifndef __MATRIX_H__
#define __MATRIX_H__

#include <assert.h>
#include "BasicType/Vector.h"
#include "BasicType/BasicType_1.h"

namespace GCRE {
	namespace BasicType {

		class Matrix33f {
			public:
			protected:
			private:
		};

		class Matrix44f {
			friend class MatrixUtitlity;
			public:
				Matrix44f();
				Matrix44f( const Matrix44f& m );
				Matrix44f( const SFFloat* pM );

				void								Print();
				void								Identity();
				void								Transpose();
				void								Inverse( SFFloat epsilon = 1e-08 );
				SFFloat							Determinant() const;
				void								SetColumn( SFInt col, const Vec4f& v );
				void								SetColumn( SFInt col, const SFFloat* c );
				void								SetRow( SFInt row, const Vec4f& v );
				void								SetRow( SFInt row, const SFFloat* r );
				Vec4f							GetColumn( SFInt col ) const;
				Vec4f							GetRow( SFInt row ) const;
				void								Transform( Vec4f& v ) const;
				void								Transform( Vec3f& v, SFFloat w ) const;
				void								SetMatrix( const SFFloat* pM );
				const SFFloat*				GetMatrix() const;

				void*							operator new( size_t size );
				void								operator delete( void *mem );
				void*							operator new[]( size_t size );
				void								operator delete[]( void *mem );
				const SFFloat*				operator[]( SFInt i ) const;
				SFFloat*						operator[]( SFInt i );
				Matrix44f&					operator=( const Matrix44f& m );
				Matrix44f						operator+( const Matrix44f& m ) const;
				Matrix44f						operator-( const Matrix44f& m ) const;
				Matrix44f&					operator+=( const Matrix44f& m );
				Matrix44f&					operator-=( const Matrix44f& m );
				Matrix44f						operator*( SFFloat f ) const;
				Matrix44f						operator/( SFFloat f ) const;
				Matrix44f&					operator*=( SFFloat f );
				Matrix44f&					operator/=( SFFloat f );
				Matrix44f						operator*( const Matrix44f& m ) const;
				friend Matrix44f			operator*( SFFloat f, const Matrix44f& m ) { return m * f; }

				//		Point AND Vector Transform
				friend Vec4f				operator*( const Vec4f& v, const Matrix44f& m );
				//		Point Transform ONLY, NOT include Vector
				friend Vec3f				operator*( const Vec3f& v, const Matrix44f& m );

			protected:

			private:
				union {
					SFFloat data[4][4];
					struct{
						__m128 row0, row1, row2, row3;
					};
				};
		
		};

		inline const SFFloat* Matrix44f::operator[]( SFInt i ) const { assert( i >=0 && i < 4 ); return data[i]; }
		inline SFFloat* Matrix44f::operator[]( SFInt i ) { assert( i >=0 && i < 4 ); return data[i]; }
		inline const SFFloat* Matrix44f::GetMatrix() const { return &data[0][0]; }
	}
}

#endif	//	__MATRIX_H__